#include "Task.hpp"
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <string>
#include <vector>
#include <unistd.h>
#include <ctime>
#include <sys/stat.h>
#include <sys/wait.h>

#define processnum 5
std::vector<task_t> tasks;

void slaver()
{
    while (1)
    {
        // sleep (1);
        // 读取任务码--控制4字节
        int cmdcode = 0;
        int n = read(0, &cmdcode, sizeof(int)); // 如果此时父进程没有发送消息，子进程处于阻塞状态
        if (n == sizeof(int))
        {
            // 子进程执行相应任务码的任务
            std::cout << "child say: " << getpid() << " : cmdcode :" << cmdcode << std::endl;
            if (cmdcode >= 0 && cmdcode < tasks.size())
                tasks[cmdcode]();
        }
        if (n == 0)
            break;
    }
}

// 先描述
class channel
{
public:
    channel(int cmdfd, pid_t slaverid, std::string &processname)
        : _cmdfd(cmdfd), _slaverid(slaverid), _processname(processname)
    {
    }

public:
    int _cmdfd;
    pid_t _slaverid;
    std::string _processname;
};

// 输入 const &
// 输出 *
// 输入输出 &
void InitProcess(std::vector<channel> *channels)
{
    std::vector<int> oldfd;
    for (int i = 0; i < processnum; i++)
    {
        // 创建管道
        int pipefd[2];
        int n = pipe(pipefd);
        assert(!n);
        (void)n;

        // 创建子进程
        int id = fork();
        if (id == 0)
        {
            // child
            std::cout<<"child : "<<getpid()<<"close oldfd : ";
            for(auto& fd:oldfd)
            {
               close(fd);
               std::cout<<fd<<" ";
            }
            std::cout<<std::endl;

            close(pipefd[1]);
            dup2(pipefd[0], 0);
            close(pipefd[0]);
            slaver();
            std::cout << "process quit : " << getpid() << std::endl;
            exit(0);
        }

        // parent
        close(pipefd[0]);

        // 添加channel字段
        std::string name = "process-" + std::to_string(i);
        channels->push_back(channel(pipefd[1], id, name));
        oldfd.push_back(pipefd[1]);
    }
}

void Debug(const std::vector<channel> &channels)
{
    for (auto &c : channels)
    {
        std::cout << c._cmdfd << " " << c._slaverid << " " << c._processname << std::endl;
    }
}

void Menu()
{
    std::cout << "######################################" << std::endl;
    std::cout << "###1.和连义鸿吃饭     2.和连义鸿散步###" << std::endl;
    std::cout << "###3.和连义鸿聊八卦   4.和连义鸿休息###" << std::endl;
    std::cout << "################0.退出################" << std::endl;
    std::cout << "######################################" << std::endl;
}

void Ctrlslaver(std::vector<channel> &channels)
{
    int cnt = 5;
    while (true)
    {
        Menu();
        int select = 0;
        std::cout << "Please Enter" << std::endl;
        std::cin >> select;

        int which = 0;
        int cnt = 5;
        // for (int i = 1; i <= 100; i++)
        // {
        // 选择任务
        // int cmdcode = rand() % tasks.size();
        if (select <= 0 || select >= 5)
            break;
        int cmdcode = select - 1;

        // 选择进程
        // int processpos = rand() % channels.size();
        which = rand() % channels.size();

        // 发送任务
        write(channels[which]._cmdfd, &cmdcode, sizeof(cmdcode));
        std::cout << "father say: " << "cmdcode: " << cmdcode << " already sendto " << channels[which]._slaverid
                  << " process name: " << channels[which]._processname << std::endl;

        which++;

        // cnt--;
        // if (cnt < 0)
        //     break;

        // sleep(1);
        // }
    }
}

void Quitslaver(std::vector<channel> &channels)
{
    // for (auto &c : channels)
    //     close(c._cmdfd); // 关闭写端
    // // sleep(5);
    // for (auto &c : channels)
    // {
    //     pid_t rid = waitpid(c._slaverid, nullptr, 0);
    //     std::cout << "father wait success : " << rid << std::endl;
    // }
    // // sleep(5);

    // verson2  从最后一个子进程开始回收
    // int last = channels.size() - 1;
    // for (int i = last; i >= 0; i--)
    // {
    //     close(channels[i]._cmdfd);
    //     pid_t rid = waitpid(channels[i]._slaverid, nullptr, 0);
    //     std::cout << "father wait success : " << rid << std::endl;
    // }

    // verson3  在继承父进程的时候关闭多余的写端
    for (auto &c : channels)
    {
        close(c._cmdfd);
        pid_t rid = waitpid(c._slaverid, nullptr, 0);
        std::cout << "father wait success : " << rid << std::endl;
    }
}

int main()
{
    srand(time(nullptr));
    LoadTask(&tasks);

    // BigAzhe();
    //  再组织
    std::vector<channel> channels;

    // 初始化
    InitProcess(&channels);

    // test
    // Debug(channels);

    // 控制子进程
    Ctrlslaver(channels);

    // 清理
    Quitslaver(channels);

    return 0;
}
